package com.copa.module.order.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.copa.constant.OrderStatusConstant;
import com.copa.constant.SubOrderStatusConstant;
import com.copa.domain.PageVo;
import com.copa.domain.ResponseDto;
import com.copa.module.goods.domain.dto.CategoryDto;
import com.copa.module.order.domain.dto.OrderDetailDto;
import com.copa.module.order.domain.dto.OrderListDto;
import com.copa.module.order.domain.entity.OrderEntity;
import com.copa.module.order.domain.entity.OrderGoodsEntity;
import com.copa.module.order.domain.entity.OrderLogEntity;
import com.copa.module.order.domain.vo.OrderApplyVo;
import com.copa.module.order.domain.vo.OrderCancelVo;
import com.copa.module.order.domain.vo.OrderConfirmVo;
import com.copa.module.order.domain.vo.OrderListVo;
import com.copa.module.order.manage.OrderManage;
import com.copa.module.order.mapper.OrderDao;
import com.copa.module.order.service.OrderLogService;
import com.copa.module.order.service.OrderService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

import static com.copa.constant.OrderStatusConstant.*;
import static com.copa.constant.SubOrderStatusConstant.*;

/**
 * @author copa
 * @createDate 2021-01-09 15:34
 * @function
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private OrderManage orderManage;

    @Autowired
    private OrderLogService orderLogService;

    @Override
    public ResponseDto<IPage<OrderListDto>> list(OrderListVo orderListVo) {
        Page<OrderListDto> page = new Page<>(orderListVo.getPageVo().getCurrent(), orderListVo.getPageVo().getSize());
        IPage<OrderListDto> orderList = new Page<>();
        if (orderListVo.getOrderStatus() != null && orderListVo.getOrderStatus() == 3) {
            orderList = orderDao.findOrderListByApplyRefund(page, orderListVo);
        } else {
            orderList = orderDao.findOrderList(page, orderListVo);
        }
        if (orderList.getTotal() > 0) {
            return ResponseDto.success(orderList);
        }
        return ResponseDto.errorMsg("抱歉，没查到该用户的订单！");
    }

    @Override
    public ResponseDto<OrderDetailDto> detail(Long orderId) {
        OrderDetailDto orderDetailDto = new OrderDetailDto();
        OrderEntity order = orderDao.selectById(orderId);
        orderDetailDto.setOrder(order);
        OrderDetailDto orderDetail = orderManage.findOrderDetailByOrderId(order);
        BeanUtils.copyProperties(orderDetail, orderDetailDto, new String[]{"order"});
        return ResponseDto.success(orderDetailDto);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseDto<String> confirmOrder(OrderConfirmVo orderConfirmVo) {
        OrderEntity order = orderDao.selectById(orderConfirmVo.getOrderId());
        if (!WAITPAY.getOrderStatus().equals(order.getOrderStatus())) {
            return ResponseDto.errorMsg("不能对该订单进行操作！");
        }

        if (!orderConfirmVo.getConfirmFlag()) {
            order.setStoreRemark(orderConfirmVo.getStoreRemark())
                    .setOrderStatus(OrderStatusConstant.STORECANCEL.getOrderStatus());
            orderDao.updateById(order);
            // 订单日志
            OrderLogEntity orderLog = OrderLogEntity.builder()
                    .message("商家取消订单")
                    .orderId(order.getOrderSn())
                    .orderStatus(OrderStatusConstant.STORECANCEL.getOrderStatus())
                    .build();
            orderLogService.addOrderLog(orderLog);
            return ResponseDto.success("取消发货成功！");
        }

        order.setOrderStatus(SHIPPED.getOrderStatus())
                .setActualPrice(orderConfirmVo.getActualPrice())
                .setExpressCompany(orderConfirmVo.getExpressCompany())
                .setExpressNum(orderConfirmVo.getExpressNum())
                .setStoreRemark(orderConfirmVo.getStoreRemark());
        orderDao.updateById(order);
        // 订单日志
        OrderLogEntity orderLog = OrderLogEntity.builder()
                .message("商家已确定订单，已发货")
                .orderId(order.getOrderSn())
                .orderStatus(SHIPPED.getOrderStatus())
                .build();
        orderLogService.addOrderLog(orderLog);
        return ResponseDto.success("确定订单成功！该订单为已发货状态！");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseDto<String> cancelOrder(OrderCancelVo orderCancelVo) {
        // 如果是总订单取消
        OrderEntity order = orderDao.selectById(orderCancelVo.getOrderId());
        if (ObjectUtil.isNull(orderCancelVo.getSubOrderId()) &&
                (OrderStatusConstant.SHIPPED.getOrderStatus().equals(order.getOrderStatus())
                || OrderStatusConstant.PARTREFUND.getOrderStatus().equals(order.getOrderStatus())
                || PAY.getOrderStatus().equals(order.getOrderStatus())
                || WAITPAY.getOrderStatus().equals(order.getOrderStatus()))) {
            order.setOrderStatus(OrderStatusConstant.STORECANCEL.getOrderStatus());
            orderDao.updateById(order);
            // 订单日志
            OrderLogEntity orderLog = OrderLogEntity.builder()
                    .message("商家取消订单")
                    .orderId(order.getOrderSn())
                    .orderStatus(OrderStatusConstant.STORECANCEL.getOrderStatus())
                    .build();
            orderLogService.addOrderLog(orderLog);
            return ResponseDto.successMsg("订单取消成功！");
        }

        // 如果是部分订单取消
        if (ObjectUtil.isNotNull(orderCancelVo.getOrderId())  &&
                ObjectUtil.isNotNull(orderCancelVo.getSubOrderId()) &&
                (OrderStatusConstant.SHIPPED.getOrderStatus().equals(order.getOrderStatus())
                        || OrderStatusConstant.PARTREFUND.getOrderStatus().equals(order.getOrderStatus())
                        || WAITPAY.getOrderStatus().equals(order.getOrderStatus())
                        || PAY.getOrderStatus().equals(order.getOrderStatus()))) {
            ResponseDto<OrderGoodsEntity> orderGoodsRes =
                    orderManage.findOrderGoodsByOrderGoodsId(orderCancelVo.getSubOrderId());
            if (orderGoodsRes.isNotSuccess()) {
                return ResponseDto.errorMsg(orderGoodsRes.getMsg());
            }
            OrderGoodsEntity orderGoods = orderGoodsRes.getData();
            if (SubOrderStatusConstant.NORMAL.getOrderStatus().equals(orderGoods.getRefundStatus())) {
                orderGoods.setRefundStatus(SubOrderStatusConstant.STOREREFUND.getOrderStatus());
                        //.setRefundStoreRemark(orderCancelVo.getRefundRemark())
                        //.setRefundTime(LocalDateTime.now());
                ResponseDto<Boolean> res = orderManage.putOrderGoodsById(orderGoods);
                if (res.isNotSuccess()) {
                    return ResponseDto.errorMsg(res.getMsg());
                }
                // 校验该订单是否所有子订单已取消，取消则改变总订单状态
                ResponseDto<List<OrderGoodsEntity>> orderGoodsListRes = orderManage.findOrderGoodsListByOrderId(orderCancelVo.getOrderId());
                if (orderGoodsRes.isNotSuccess()) {
                    return ResponseDto.errorMsg(orderGoodsListRes.getMsg());
                }
                boolean allRefundOrderFlag = true;
                for (OrderGoodsEntity orderGoodsEntity : orderGoodsListRes.getData()) {
                    if (SubOrderStatusConstant.NORMAL.getOrderStatus().equals(orderGoodsEntity.getRefundStatus())
                        || APPLYREFUND.getOrderStatus().equals(orderGoodsEntity.getRefundStatus())) {
                        allRefundOrderFlag = false;
                        break;
                    }
                }
                if (allRefundOrderFlag) {
                    order.setOrderStatus(OrderStatusConstant.REFUND.getOrderStatus());
                    // 订单日志
                    OrderLogEntity orderLog = OrderLogEntity.builder()
                            .message("商家取消该子订单【"+orderGoods.getOrderGoodsSn()+"】,总订单已经全部取消")
                            .orderId(order.getOrderSn())
                            .orderGoodsId(orderGoods.getOrderGoodsSn())
                            .orderStatus(OrderStatusConstant.REFUND.getOrderStatus())
                            .subOrderStatus(STOREREFUND.getOrderStatus())
                            .build();
                    orderLogService.addOrderLog(orderLog);
                } else {
                    order.setOrderStatus(OrderStatusConstant.PARTREFUND.getOrderStatus());
                    // 订单日志
                    OrderLogEntity orderLog = OrderLogEntity.builder()
                            .message("商家取消子订单【"+orderGoods.getOrderGoodsSn()+"】")
                            .orderId(order.getOrderSn())
                            .orderGoodsId(orderGoods.getOrderGoodsSn())
                            .orderStatus(OrderStatusConstant.STORECANCEL.getOrderStatus())
                            .subOrderStatus(STOREREFUND.getOrderStatus())
                            .build();
                    orderLogService.addOrderLog(orderLog);
                }
                orderDao.updateById(order);
                return ResponseDto.successMsg("取消订单成功！");
            }
        }

        return ResponseDto.errorMsg("该订单不能取消！");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseDto<String> applyRefundOrder(OrderApplyVo orderApplyVo) {
        OrderEntity order = orderDao.selectById(orderApplyVo.getOrderId());
        if (ObjectUtil.isNull(order)) {
            return ResponseDto.successMsg("找不到该订单！");
        }
        if (USERCANCEL.getOrderStatus().equals(order.getOrderStatus())
            || STORECANCEL.getOrderStatus().equals(order.getOrderStatus())
            || REFUND.getOrderStatus().equals(order.getOrderStatus())) {
            return ResponseDto.errorMsg("该订单不可操作！");
        }

        // 申请退款必须一件一件来，不能总订单一起
        if (ObjectUtil.isNotNull(orderApplyVo.getSubOrderId())) {
            ResponseDto<OrderGoodsEntity> orderGoodsRes = orderManage.findOrderGoodsByOrderGoodsId(orderApplyVo.getSubOrderId());
            if (orderGoodsRes.isNotSuccess()) {
                return ResponseDto.errorMsg(orderGoodsRes.getMsg());
            }
            OrderGoodsEntity orderGoods = orderGoodsRes.getData();
            if (APPLYREFUND.getOrderStatus().equals(orderGoods.getRefundStatus())) {
                if (!orderApplyVo.getConfirmFlag()) {
                    orderGoods.setRefundStatus(NORMAL.getOrderStatus());
                    orderManage.putOrderGoodsById(orderGoods);
                    // 订单日志
                    OrderLogEntity orderLog = OrderLogEntity.builder()
                            .message("商家拒绝退款子订单【"+orderGoods.getOrderGoodsSn()+"】")
                            .orderId(order.getOrderSn())
                            .orderGoodsId(orderGoods.getOrderGoodsSn())
                            .orderStatus(order.getOrderStatus())
                            .subOrderStatus(NORMAL.getOrderStatus())
                            .build();
                    orderLogService.addOrderLog(orderLog);
                    // 校验该订单是否所有子订单都没有退款状态，如果是则改变总订单状态
                    ResponseDto<List<OrderGoodsEntity>> orderGoodsListRes = orderManage.findOrderGoodsListByOrderId(orderApplyVo.getOrderId());
                    if (orderGoodsRes.isNotSuccess()) {
                        return ResponseDto.errorMsg(orderGoodsListRes.getMsg());
                    }
                    boolean allRefundOrderFlag = true;
                    for (OrderGoodsEntity orderGoodsEntity : orderGoodsListRes.getData()) {
                        if (!SubOrderStatusConstant.NORMAL.getOrderStatus().equals(orderGoodsEntity.getRefundStatus())) {
                            allRefundOrderFlag = false;
                            break;
                        }
                    }
                    if (allRefundOrderFlag) {
                        order.setOrderStatus(SHIPPED.getOrderStatus());
                        orderDao.updateById(order);
                    }
                    return ResponseDto.successMsg("操作成功！");
                }
                orderGoods.setRefundStatus(USERREFUND.getOrderStatus());
                        //.setRefundTime(LocalDateTime.now())
                        //.setRefundStoreRemark(orderApplyVo.getRefundRemark());
                ResponseDto<Boolean> orderGoodRefundFlagRes = orderManage.putOrderGoodsById(orderGoods);
                if (orderGoodRefundFlagRes.isNotSuccess()) {
                    return ResponseDto.errorMsg(orderGoodRefundFlagRes.getMsg());
                }
                // 校验该订单是否所有子订单已退款，如果是则改变总订单状态
                ResponseDto<List<OrderGoodsEntity>> orderGoodsListRes = orderManage.findOrderGoodsListByOrderId(orderApplyVo.getOrderId());
                if (orderGoodsRes.isNotSuccess()) {
                    return ResponseDto.errorMsg(orderGoodsListRes.getMsg());
                }
                boolean allRefundOrderFlag = true;
                for (OrderGoodsEntity orderGoodsEntity : orderGoodsListRes.getData()) {
                    if (SubOrderStatusConstant.NORMAL.getOrderStatus().equals(orderGoodsEntity.getRefundStatus())
                            || APPLYREFUND.getOrderStatus().equals(orderGoodsEntity.getRefundStatus())) {
                        allRefundOrderFlag = false;
                        break;
                    }
                }
                if (allRefundOrderFlag) {
                    order.setOrderStatus(OrderStatusConstant.REFUND.getOrderStatus());
                    // 订单日志
                    OrderLogEntity orderLog = OrderLogEntity.builder()
                            .message("商家同意退款子订单【"+orderGoods.getOrderGoodsSn()+"】，总订单已取消")
                            .orderId(order.getOrderSn())
                            .orderGoodsId(orderGoods.getOrderGoodsSn())
                            .orderStatus(OrderStatusConstant.REFUND.getOrderStatus())
                            .subOrderStatus(USERREFUND.getOrderStatus())
                            .build();
                    orderLogService.addOrderLog(orderLog);
                } else {
                    order.setOrderStatus(OrderStatusConstant.PARTREFUND.getOrderStatus());
                    // 订单日志
                    OrderLogEntity orderLog = OrderLogEntity.builder()
                            .message("商家同意退款子订单【"+orderGoods.getOrderGoodsSn()+"】")
                            .orderId(order.getOrderSn())
                            .orderGoodsId(orderGoods.getOrderGoodsSn())
                            .orderStatus(OrderStatusConstant.PARTREFUND.getOrderStatus())
                            .subOrderStatus(USERREFUND.getOrderStatus())
                            .build();
                    orderLogService.addOrderLog(orderLog);
                }
                orderDao.updateById(order);
                return ResponseDto.successMsg("操作成功！");
            }
        }

        return ResponseDto.errorMsg("该订单不可操作！");
    }

    @Override
    public Long findAddTotalOrderNumByTime(LocalDate now, LocalDate yesterday) {
        return orderDao.findAddTotalOrderNumByTime(now, yesterday);
    }

    @Override
    public Long findAddOrderGoodsNumByTime(LocalDate now, LocalDate yesterday) {
        return orderDao.findAddOrderGoodsNumByTime(now, yesterday);
    }

    @Override
    public Long findAddPayTotalOrderNumByTime(LocalDate now, LocalDate yesterday) {
        return orderDao.findAddPayTotalOrderNumByTime(now, yesterday);
    }

    @Override
    public Long findAddPayOrderGoodsNumByTime(LocalDate now, LocalDate yesterday) {
        return orderDao.findAddPayOrderGoodsNumByTime(now, yesterday);
    }

    @Override
    public Long findRefundOrderGoodsNumByTime(LocalDate now, LocalDate yesterday) {
        return orderDao.findRefundOrderGoodsNumByTime(now, yesterday);
    }

    @Override
    public BigDecimal findIncomeByTime(LocalDate now, LocalDate yesterday) {
        return orderDao.findIncomeByTime(now, yesterday);
    }

    @Override
    public BigDecimal findRefundByTime(LocalDate now, LocalDate yesterday) {
        return orderDao.findRefundByTime(now, yesterday);
    }

    @Override
    public Long findAddSaleGoodsNumByTime(LocalDate now, LocalDate yesterday) {
        return orderDao.findAddSaleGoodsNumByTime(now, yesterday);
    }

    @Override
    public Long findRefundSaleGoodsNumByTime(LocalDate now, LocalDate yesterday) {
        return orderDao.findRefundSaleGoodsNumByTime(now, yesterday);
    }
}
